/**
 * 认证插件
 * 提供 JWT 认证和权限验证的装饰器
 */

import { FastifyPluginAsync, FastifyRequest, FastifyReply } from 'fastify'
import fp from 'fastify-plugin'
import { verifyToken, checkOrgPermission, checkGlobalAdmin, checkModeratorPermission } from '@services/auth.service'
import { UnauthorizedError, PermissionError } from '@services/common/errors'
import { TokenPayload } from '@services/common/types'

// 扩展 FastifyRequest 类型，添加 user 属性
declare module 'fastify' {
    interface FastifyRequest {
        user?: TokenPayload
    }
}

/**
 * 从请求头中提取 JWT Token
 */
function extractToken(request: FastifyRequest): string | null {
    const authHeader = request.headers.authorization

    if (!authHeader) {
        return null
    }

    // 支持 "Bearer <token>" 格式
    if (authHeader.startsWith('Bearer ')) {
        return authHeader.substring(7)
    }

    // 直接返回 token
    return authHeader
}

/**
 * JWT 认证装饰器
 * 验证 Token 并将用户信息注入到 request.user
 */
export async function authenticate(request: FastifyRequest, reply: FastifyReply): Promise<void> {
    try {
        const token = extractToken(request)

        if (!token) {
            throw new UnauthorizedError('缺少认证令牌')
        }

        // 验证 Token
        const payload = await verifyToken(token)

        if (!payload) {
            throw new UnauthorizedError('令牌无效或已过期')
        }

        // 将用户信息注入到请求对象
        request.user = payload
    } catch (error) {
        if (error instanceof UnauthorizedError) {
            throw error
        }
        throw new UnauthorizedError('认证失败')
    }
}

/**
 * 可选认证装饰器
 * 如果有 Token 则验证，没有则跳过（不抛出错误）
 */
export async function optionalAuthenticate(request: FastifyRequest, reply: FastifyReply): Promise<void> {
    try {
        const token = extractToken(request)

        if (token) {
            const payload = await verifyToken(token)
            if (payload) {
                request.user = payload
            }
        }
    } catch (error) {
        // 静默失败，不影响后续处理
        request.log.debug('可选认证失败')
    }
}

/**
 * 要求管理员权限
 * 必须先调用 authenticate
 */
export async function requireAdmin(request: FastifyRequest, reply: FastifyReply): Promise<void> {
    if (!request.user) {
        throw new UnauthorizedError('请先登录')
    }

    if (request.user.userType !== 'admin') {
        throw new PermissionError('需要管理员权限')
    }
}

/**
 * 要求成员权限
 * 必须先调用 authenticate
 */
export async function requireMember(request: FastifyRequest, reply: FastifyReply): Promise<void> {
    if (!request.user) {
        throw new UnauthorizedError('请先登录')
    }

    if (request.user.userType !== 'member') {
        throw new PermissionError('需要成员权限')
    }
}

/**
 * 要求全局管理员权限
 * 检查管理员是否有全局管理权限
 */
export async function requireGlobalAdmin(request: FastifyRequest, reply: FastifyReply): Promise<void> {
    if (!request.user) {
        throw new UnauthorizedError('请先登录')
    }

    if (request.user.userType !== 'admin') {
        throw new PermissionError('需要管理员权限')
    }

    const isGlobal = await checkGlobalAdmin(request.user.userId)
    if (!isGlobal) {
        throw new PermissionError('需要全局管理员权限')
    }
}

/**
 * 要求组织管理员权限
 * @param organizationId 组织ID（从路由参数或请求体获取）
 */
function createRequireOrgAdmin(organizationId: string) {
    return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {
        if (!request.user) {
            throw new UnauthorizedError('请先登录')
        }

        if (request.user.userType !== 'admin') {
            throw new PermissionError('需要管理员权限')
        }

        const hasPermission = await checkOrgPermission(request.user.userId, organizationId)
        if (!hasPermission) {
            throw new PermissionError('您没有该组织的管理权限')
        }
    }
}

/**
 * 要求协管权限（协管或管理员）
 * @param organizationId 组织ID
 */
function createRequireModerator(organizationId: string) {
    return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {
        if (!request.user) {
            throw new UnauthorizedError('请先登录')
        }

        if (request.user.userType !== 'admin') {
            throw new PermissionError('需要管理员权限')
        }

        const hasPermission = await checkModeratorPermission(request.user.userId, organizationId)
        if (!hasPermission) {
            throw new PermissionError('您没有该组织的协管权限')
        }
    }
}

/**
 * 验证是否为资源拥有者
 * @param resourceUserId 资源所属用户ID
 */
async function requireOwner(request: FastifyRequest, resourceUserId: string): Promise<void> {
    if (!request.user) {
        throw new UnauthorizedError('请先登录')
    }

    // 管理员可以访问任何资源
    if (request.user.userType === 'admin') {
        return
    }

    // 成员只能访问自己的资源
    if (request.user.userId !== resourceUserId) {
        throw new PermissionError('您只能访问自己的资源')
    }
}

/**
 * 验证是否为资源拥有者或管理员
 */
async function requireOwnerOrAdmin(request: FastifyRequest, resourceUserId: string): Promise<void> {
    if (!request.user) {
        throw new UnauthorizedError('请先登录')
    }

    const isOwner = request.user.userId === resourceUserId
    const isAdmin = request.user.userType === 'admin'

    if (!isOwner && !isAdmin) {
        throw new PermissionError('您没有权限访问此资源')
    }
}

/**
 * 认证插件
 * 将认证装饰器注册到 Fastify 实例
 */
const authPlugin: FastifyPluginAsync = async (fastify, opts) => {
    // 注册装饰器到 Fastify 实例
    fastify.decorate('authenticate', authenticate)
    fastify.decorate('optionalAuthenticate', optionalAuthenticate)
    fastify.decorate('requireAdmin', requireAdmin)
    fastify.decorate('requireMember', requireMember)
    fastify.decorate('requireGlobalAdmin', requireGlobalAdmin)
}

// 扩展 Fastify 实例类型
declare module 'fastify' {
    interface FastifyInstance {
        authenticate: typeof authenticate
        optionalAuthenticate: typeof optionalAuthenticate
        requireAdmin: typeof requireAdmin
        requireMember: typeof requireMember
        requireGlobalAdmin: typeof requireGlobalAdmin
    }
}

export default fp(authPlugin, {
    name: 'auth',
    dependencies: []
})

// 导出所有认证函数供路由使用
export { createRequireOrgAdmin, createRequireModerator, requireOwner, requireOwnerOrAdmin }
